﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Globalization;
using System.Linq;
using System.Net.Mail;
using System.Web;
using System.Web.Mvc;
using SportMeetingPlanner.Models;
using SportMeetingPlanner.Utils;
using SportMeetingPlanner.ViewModels;

namespace SportMeetingPlanner.Controllers
{
    public class MeetingController : Controller
    {
        private SportMeetingEntities storeDB;
        SmtpClient smtp;

        public MeetingController()
            : base()
        {
            smtp = new SmtpClient();
        }

        //
        // GET: /Meeting/Details/5
        public ViewResult Details(int id)
        {
            using (storeDB = new SportMeetingEntities())
            {
                Meeting meeting = storeDB.Meetings.Include(s => s.Sport).Where(m => m.MeetingId == id).FirstOrDefault();

                IList<Subscription> subscriptions = storeDB.Subscriptions.Where(s => s.Meeting.MeetingId == meeting.MeetingId).ToList();

                SubscriptionsViewModel subscriptionsViewModel = new SubscriptionsViewModel(meeting, subscriptions, User.Identity.Name);
                return View(subscriptionsViewModel);
            }
        }

        //
        // GET: /Meeting/Create
        public ActionResult Create(int sportId)
        {
            using (storeDB = new SportMeetingEntities())
            {
                var sport = storeDB.Sports.Single(s => s.SportId == sportId);

                if (sport != null)
                {
                    Meeting m = new Meeting();
                    m.Sport = sport;
                    ViewBag.Sport = sport.Name;
                    ViewBag.SportId = sportId;
                    return View(m);
                }
                return View();
            }
        }

        //
        // POST: /Meeting/Create
        [HttpPost]
        public ActionResult Create(Meeting meeting)
        {
            using (storeDB = new SportMeetingEntities())
            {
                if (ModelState.IsValid)
                {
                    meeting.UserName = User.Identity.Name;
                    storeDB.Meetings.Add(meeting);
                    storeDB.SaveChanges();
                    HttpContext.Response.Cookies.Add(new HttpCookie("Message", "Meeting added. Use the filter to view it."));
                    return RedirectToAction("Index", new { sportId = meeting.SportId });
                }

                ViewBag.SportId = meeting.SportId;
                return View(meeting);
            }
        }

        //
        // GET: /Meeting/Edit/5
        public ActionResult Edit(int id)
        {
            using (storeDB = new SportMeetingEntities())
            {
                Meeting meeting = storeDB.Meetings.Include(s => s.Sport).Where(m => m.MeetingId == id).FirstOrDefault();
                if (meeting.UserName == User.Identity.Name)
                {
                    return View(meeting);
                }
                else
                {
                    return RedirectToAction("Index", "Home");
                }
            }
        }

        //
        // POST: /Meeting/Edit/5
        [HttpPost]
        public ActionResult Edit(Meeting meeting)
        {
            if (ModelState.IsValid)
            {
                DateTime originalDate;
                String eventCreator;
                using (storeDB = new SportMeetingEntities())
                {
                    Meeting originalMeeting = storeDB.Meetings.Where(m => m.MeetingId == meeting.MeetingId).FirstOrDefault();
                    originalDate = originalMeeting.Date;
                    eventCreator = originalMeeting.UserName;
                }

                if (eventCreator == User.Identity.Name)
                {
                    using (storeDB = new SportMeetingEntities())
                    {
                        storeDB.Entry(meeting).State = EntityState.Modified;
                        storeDB.SaveChanges();

                        if (!originalDate.Equals(meeting.Date))
                        {
                            foreach (Subscription subscription in storeDB.Subscriptions.Where(s => s.MeetingId == meeting.MeetingId))
                            {
                                MailMessage mm = new MailMessage();
                                mm.Body = string.Format("The meeting that you subscribed to, {0}, has been rescheduled on {1}", subscription.Meeting.Title, subscription.Meeting.Date);
                                mm.Subject = "Rescheduled meeting";
                                mm.From = new MailAddress("smpadmin@fortech.ro");
                                User subscriber = storeDB.Users.Find(subscription.UserName);
                                mm.To.Add(new MailAddress(subscriber.Email));

                                smtp.SendAsync(mm, null);
                            }
                        }
                    }

                    HttpContext.Response.Cookies.Add(new HttpCookie("Message", "Meeting changed. Use the filter to view it."));
                    return RedirectToAction("Index", new { sportId = meeting.SportId });
                }
                else
                {
                    return RedirectToAction("Index", "Home");
                }
            }

            using (storeDB = new SportMeetingEntities())
            {
                meeting = storeDB.Meetings.Include(s => s.Sport).Where(m => m.MeetingId == meeting.MeetingId).FirstOrDefault();
            }

            return View(meeting);
        }

        //
        // GET: /Meeting/Delete/5
        public ActionResult Delete(int id)
        {
            using (storeDB = new SportMeetingEntities())
            {
                Meeting meeting;
                using (storeDB = new SportMeetingEntities())
                {
                    meeting = storeDB.Meetings.Find(id);
                }

                return View(meeting);
            }
        }

        //
        // POST: /Meeting/Delete/5
        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {
            using (storeDB = new SportMeetingEntities())
            {
                Meeting meeting = storeDB.Meetings.Find(id);
                storeDB.Meetings.Remove(meeting);
                storeDB.SaveChanges();
                return RedirectToAction("Index");
            }
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
        }

        [Authorize]
        public ActionResult Index(int sportId)
        {
            using (storeDB = new SportMeetingEntities())
            {
                if (sportId > 0)
                {
                    var sport = storeDB.Sports.Single(s => s.SportId == sportId);

                    if (sport != null)
                    {
                        DateTime startDate;
                        DateTime endDate;

                        HttpContext.Session.Timeout = 5;
                        if (HttpContext.Session["StartDate"] == null)
                        {
                            HttpContext.Session.Add("StartDate", DateTime.Now.StartOfWeek(DayOfWeek.Sunday));
                            startDate = DateTime.Now.StartOfWeek(DayOfWeek.Sunday);
                        }
                        else
                        {
                            DateTime aux;
                            if (DateTime.TryParse(HttpContext.Session["StartDate"].ToString(), out aux))
                            {
                                startDate = aux;
                            }
                            else
                            {
                                startDate = DateTime.Now.StartOfWeek(DayOfWeek.Sunday);
                            }
                        }

                        if (HttpContext.Session["EndDate"] == null)
                        {
                            HttpContext.Session.Add("EndDate", DateTime.Now.StartOfWeek(DayOfWeek.Saturday));
                            endDate = DateTime.Now.StartOfWeek(DayOfWeek.Saturday);
                        }
                        else
                        {
                            DateTime aux;
                            if (DateTime.TryParse(HttpContext.Session["EndDate"].ToString(), out aux))
                            {
                                endDate = aux;
                            }
                            else
                            {
                                endDate = DateTime.Now.StartOfWeek(DayOfWeek.Saturday);
                            }
                        }

                        MeetingViewModel meetingsView = GetMeetingsView(sport, startDate, endDate);
                        ViewBag.Sport = sport.Name;
                        ViewBag.SportId = sportId;

                        if (HttpContext.Request.Cookies["Message"] != null && HttpContext.Request.Cookies["Message"].Value != string.Empty)
                        {
                            ModelState.AddModelError("", HttpContext.Request.Cookies["Message"].Value);
                            HttpContext.Response.Cookies["Message"].Value = string.Empty;
                        }

                        return View(meetingsView);
                    }
                }

                return View();
            }
        }

        [Authorize]
        [HttpPost]
        public ActionResult Index(int sportId, string initDate, string finalDate)
        {
            using (storeDB = new SportMeetingEntities())
            {
                var sport = storeDB.Sports.Single(s => s.SportId == sportId);
                DateTime initDateDate, finalDateDate;

                if (!(DateTime.TryParseExact(initDate, string.Format("dd/MM/yyyy"), null, DateTimeStyles.None, out initDateDate)))
                {
                    initDateDate = DateTime.MinValue;
                }

                if (!(DateTime.TryParseExact(finalDate, string.Format("dd/MM/yyyy"), null, DateTimeStyles.None, out finalDateDate)))
                {
                    finalDateDate = DateTime.MinValue;
                }

                if (sport != null)
                {
                    MeetingViewModel meetingsView = GetMeetingsView(sport, initDateDate, finalDateDate);

                    if (meetingsView.Meetings.Count == 0)
                    {
                        ModelState.AddModelError("", "Filter operation yielded no results");
                    }

                    ViewBag.Sport = sport.Name;
                    ViewBag.SportId = sport.SportId;

                    if (HttpContext.Session["StartDate"] != null)
                    {
                        HttpContext.Session["StartDate"] = meetingsView.StartDate;
                    }

                    if (HttpContext.Session["EndDate"] != null)
                    {
                        HttpContext.Session["EndDate"] = meetingsView.EndDate;
                    }

                    return View(meetingsView);
                }

                return View(); //TODO improve
            }
        }

        [HttpPost]
        public ActionResult Subscribe(Subscription subscription)
        {
            using (storeDB = new SportMeetingEntities())
            {
                if (ModelState.IsValid)
                {
                    if (subscription.SubscriptionId > 0) //Modify existent subscription
                    {
                        subscription.MeetingId = subscription.Meeting.MeetingId;
                        storeDB.Entry(subscription).State = EntityState.Modified;
                        storeDB.SaveChanges();
                    }
                    else //Add new
                    {
                        subscription.Meeting = storeDB.Meetings.Find(subscription.Meeting.MeetingId);
                        storeDB.Subscriptions.Add(subscription);
                        storeDB.SaveChanges();

                        User subscriber = storeDB.Users.Find(subscription.UserName);


                        MailMessage mail = new MailMessage();
                        mail.Subject = "Meeting subscription";
                        mail.Body = string.Format("You have just subscribed to {0} scheduled for {1}", subscription.Meeting.Title, subscription.Meeting.Date);
                        mail.From = new MailAddress("smpadmin@fortech.ro");
                        mail.To.Add(new MailAddress(subscriber.Email, subscriber.UserName));
                        smtp.SendAsync(mail, null);
                    }

                    return RedirectToAction("Details", new { id = subscription.MeetingId });
                }

                return View(subscription);
            }
        }

        public ActionResult Unsubscribe(int id)
        {
            using (storeDB = new SportMeetingEntities())
            {
                var subscriptions = storeDB.Subscriptions.Include(s => s.Meeting).Where(s => s.MeetingId == id && s.UserName == User.Identity.Name);

                if (subscriptions.Count() > 0)
                {
                    Subscription subscription = subscriptions.FirstOrDefault();

                    MailMessage mm = new MailMessage();
                    mm.Body = string.Format("You have just unsubscribed from {0} scheduled for {1}", subscription.Meeting.Title, subscription.Meeting.Date);
                    mm.Subject = "Meeting unsubscription";
                    mm.From = new MailAddress("smpadmin@fortech.ro");
                    User subscriber = storeDB.Users.Find(subscription.UserName);
                    mm.To.Add(new MailAddress(subscriber.Email));
                    smtp.SendAsync(mm, null);

                    storeDB.Subscriptions.Remove(subscription);
                    storeDB.SaveChanges();
                }

                return RedirectToAction("Details", new { id = id });
            }
        }

        public ActionResult Subscribe(int id)
        {
            using (storeDB = new SportMeetingEntities())
            {
                Subscription subscription;
                var subscriptions = storeDB.Subscriptions.Include(s => s.Meeting).Where(s => s.MeetingId == id && s.UserName == User.Identity.Name);

                if (subscriptions.Count() == 0) //new subscription
                {
                    subscription = new Subscription();

                    Meeting meeting = storeDB.Meetings.Include(s => s.Sport).Where(m => m.MeetingId == id).FirstOrDefault();

                    subscription.MeetingId = meeting.MeetingId;
                    subscription.Meeting = meeting;
                    subscription.UserName = User.Identity.Name;
                }
                else //update existing subscription
                {
                    subscription = subscriptions.FirstOrDefault();
                }

                return View(subscription);
            }
        }

        private MeetingViewModel GetMeetingsView(Sport sport)
        {
            return GetMeetingsView(sport, DateTime.MinValue, DateTime.MinValue);
        }

        private MeetingViewModel GetMeetingsView(Sport sport, DateTime initDate, DateTime finalDate)
        {
            IList<Meeting> meetings;

            if (initDate != DateTime.MinValue && finalDate != DateTime.MinValue)
            {
                meetings = storeDB.Meetings.Where(m => m.Sport.SportId == sport.SportId).Where(a => a.Date >= initDate && a.Date <= finalDate).OrderBy(a => a.Date).ToList();
            }
            else
            {
                meetings = storeDB.Meetings.Where(m => m.Sport.SportId == sport.SportId).OrderBy(a => a.Date).ToList();
            }

            IList<ExtendedMeeting> meetingsList = new List<ExtendedMeeting>();
            MeetingViewModel meetingViewModel = new MeetingViewModel();

            foreach (Meeting m in meetings)
            {
                ExtendedMeeting mViewItem = new ExtendedMeeting(m);
                var subscriptions = storeDB.Subscriptions.Where(s => s.Meeting.MeetingId == m.MeetingId);
                mViewItem.Players = subscriptions.Count() > 0 ? subscriptions.Sum(s => s.NrPersons) : 0;
                meetingsList.Add(mViewItem);
            }

            meetingViewModel.Meetings = meetingsList;
            meetingViewModel.StartDate = initDate;
            meetingViewModel.EndDate = finalDate;
            meetingViewModel.SportId = sport.SportId;
            meetingViewModel.SportName = sport.Name;

            return meetingViewModel;
        }
    }
}